package com.face.server.dao;

import com.face.server.entity.Student;
import com.face.server.entity.Visitor;
import com.face.server.service.UtileService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;


import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static org.springframework.data.mongodb.core.query.Criteria.where;

@Repository
public class VisitorDAO {

    @Autowired
    MongoTemplate mongoTemplate;

    public long countByStudentId(String id, Date now) {
        return mongoTemplate.count(Query.query(
                where("student.$id").is(new ObjectId(id))
                        .and("effectDate").lte(now)
                        .and("endDate").gte(now)
                        .and("type").is(1)
        ), Visitor.class, "joined");
    }

    public Visitor findOne(String id) {
        return mongoTemplate.findById(id, Visitor.class, "joined");
    }

    public List<Visitor> findByStudentId(String id, Date now) {
        return mongoTemplate.find(Query.query(
                where("student.$id").is(new ObjectId(id))
                        .and("effectDate")
                        .lte(now).and("endDate")
                        .gte(now).and("type").is(1)
        ), Visitor.class, "joined");
    }

    public Long countVisitors() {
        return mongoTemplate.count(Query.query(
                where("type").is(1)
        ),Visitor.class,"joined");
    }

    public Long countVisitors(Integer buildNum) {
        return mongoTemplate.count(Query.query(
                where("type").is(1).and("dormitoryBuildNum").is(buildNum)
        ),Visitor.class,"joined");
    }

    public List<Visitor> listVisitors(Pageable pageable, String key) {
        if (key==null||key.equals("")){
            Aggregation aggregation=Aggregation.newAggregation(
                    Aggregation.match(new Criteria("type").is(1)),
                    Aggregation.sort(pageable.getSort()),
                    Aggregation.limit(pageable.getPageSize()),
                    Aggregation.skip((long)pageable.getOffset())
            );
            return mongoTemplate.aggregate(aggregation,"joined",Visitor.class).getMappedResults();
        }
        int page=pageable.getPageNumber()>0?pageable.getPageNumber()*pageable.getPageSize():0;
        List<Student> students=mongoTemplate.find(Query.query(
           where("type").is(0).and("name").regex(key)
        ),Student.class,"joined");
        List<String> idlist=new ArrayList<String>();
        if (students!=null&&students.size()>0){
            students.stream().forEach(e->
                    idlist.add(e.getId())
            );
        }
        Criteria criteria=new Criteria();

        Criteria cristu=new Criteria();
        if (idlist!=null&&idlist.size()>0)
            cristu.and("student.$id").in(idlist);
        criteria.orOperator(cristu,new Criteria("name").regex(key));
        Criteria criteria1=new Criteria();
        if (UtileService.isNum(key))
            criteria1.orOperator(new Criteria("dormitoryBuildNum").is(Integer.parseInt(key)),new Criteria("dormitoryNum").is(Integer.parseInt(key)));
        Aggregation aggregation=Aggregation.newAggregation(
                Aggregation.match(new Criteria().orOperator(criteria,criteria1)),
                Aggregation.sort(pageable.getSort()),
                Aggregation.skip((long)pageable.getOffset()),
                Aggregation.limit(pageable.getPageSize())
        );
        List<Visitor> visitors=mongoTemplate.aggregate(aggregation,"joined",Visitor.class).getMappedResults();
        return visitors;
    }

    public List<Visitor> listVisitors(Pageable pageable, String key, List<Integer> dormitoryNumList) {
        if (key==null||key.equals("")){
            Aggregation aggregation=Aggregation.newAggregation(
                    Aggregation.match(new Criteria("type").is(1).and("dormitoryBuildNum").in(dormitoryNumList)),
                    Aggregation.sort(pageable.getSort()),
                    Aggregation.limit(pageable.getPageSize()),
                    Aggregation.skip((long)pageable.getOffset())
            );
            return mongoTemplate.aggregate(aggregation,"joined",Visitor.class).getMappedResults();
        }
        int page=pageable.getPageNumber()>0?pageable.getPageNumber()*pageable.getPageSize():0;
        List<Student> students=mongoTemplate.find(Query.query(
                where("type").is(0).and("name").regex(key).and("dormitoryBuildNum").in(dormitoryNumList)
        ),Student.class,"joined");
        List<String> idlist=new ArrayList<String>();
        if (students!=null&&students.size()>0){
            students.stream().forEach(e->
                    idlist.add(e.getId())
            );
        }
        Criteria criteria=new Criteria();

        Criteria cristu=new Criteria();
        if (idlist!=null&&idlist.size()>0)
            cristu.and("student.$id").in(idlist);
        criteria.orOperator(cristu,new Criteria("name").regex(key));
        Criteria criteria1=new Criteria();
        if (UtileService.isNum(key))
            criteria1.orOperator(new Criteria("dormitoryBuildNum").is(Integer.parseInt(key)),new Criteria("dormitoryNum").is(Integer.parseInt(key)));
        Aggregation aggregation=Aggregation.newAggregation(
                Aggregation.match(new Criteria().orOperator(criteria,new Criteria().andOperator(criteria1,new Criteria("dormitoryBuildNum").in(dormitoryNumList)))),
                Aggregation.sort(pageable.getSort()),
                Aggregation.skip((long)pageable.getOffset()),
                Aggregation.limit(pageable.getPageSize())
        );
        List<Visitor> visitors=mongoTemplate.aggregate(aggregation,"joined",Visitor.class).getMappedResults();
        return visitors;
    }
}
